/**
  ******************************************************************************
  * @file   pd_h_dma.c
  * @author Chris
  * @since  2023/11/22
  *
  * @brief  Peripheral driver of DMA(Hardware-Implemented).
  *
  ******************************************************************************
  */

#include "stm32g4xx_ll_bus.h"
#include "stm32g4xx_ll_dma.h"

/** region Declaration and Definition Region */

/** region Variables and Constants Region */
uint8_t dmaSize = 0;
/** endregion Variables and Constants Region */

/** region Function Declaration Region */
/** endregion Function Declaration Region */

/** endregion Declaration and Definition Region */



/** region public function region */
/**
 * @brief   DMA1 初始化
 *
 * @note    无
 * @param   addrA   源地址
 * @param   addrB   目标地址
 * @param   size    待转运的数据长度
 * @retval  无
 */
void PD_H_DMA1_Init(uint32_t addrA, uint32_t addrB, uint32_t size) {
    dmaSize = size;
    // 开启时钟
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);

    // DMA 初始化
    LL_DMA_InitTypeDef DMA_InitStruct;
    DMA_InitStruct.PeriphOrM2MSrcAddress = addrA;                   // 外设或存储器源地址
    DMA_InitStruct.MemoryOrM2MDstAddress = addrB;                   // 内存或存储器目标地址
    DMA_InitStruct.Direction = LL_DMA_DIRECTION_MEMORY_TO_MEMORY;   // 传输方向
    DMA_InitStruct.Mode = LL_DMA_MODE_NORMAL;                       // 是否自动重装 size。NORMAL 表示不重装
    DMA_InitStruct.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_INCREMENT; // 源数据地址是否自增
    DMA_InitStruct.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; // 目标数据地址是否自增
    DMA_InitStruct.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; // 源数据宽度
    DMA_InitStruct.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; // 目标数据宽度
    DMA_InitStruct.NbData = size;                                   // 待传输数据大小
    DMA_InitStruct.PeriphRequest = LL_DMAMUX_REQ_MEM2MEM;           // 软件或硬件触发
    DMA_InitStruct.Priority = LL_DMA_PRIORITY_MEDIUM;               // 优先级
    LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &DMA_InitStruct);

    // DMA 工作必要条件：计数器、触发源、DMA 使能
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
}

/**
 * @brief   DMA1 数据转运
 *
 * @note    无
 * @retval  无
 */
void PD_H_DMA1_Transfer(void) {
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
    LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, dmaSize);
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);

    while (LL_DMA_IsActiveFlag_TC1(DMA1) == RESET); // 通道 1 转运完成标志
    LL_DMA_ClearFlag_TC1(DMA1);
}
/** endregion public function region */



/** region private function region */

/** endregion private function region */
